package cn.sdack.go.users.service;

import cn.sdack.go.common.annotation.AfterAuthentication;
import cn.sdack.go.common.annotation.BeforeAuthentication;
import cn.sdack.go.common.entities.users.AuthorityEntity;
import cn.sdack.go.common.entities.users.GroupEntity;
import cn.sdack.go.common.entities.users.UserAuthorityEntity;
import cn.sdack.go.common.entities.users.UserEntity;
import cn.sdack.go.users.dao.AuthorityDao;
import cn.sdack.go.users.dao.GroupDao;
import cn.sdack.go.users.dao.UserAuthorityDao;
import cn.sdack.go.users.dao.UserDao;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author sdack
 * @date 2024/2/11
 */
@Service
public class GroupServiceImpl implements GroupService {

    @Autowired
    private GroupDao groupDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserAuthorityDao userAuthorityDao;

    @Autowired
    private AuthorityDao authorityDao;

    @Autowired
    private UserService  userService;

    @AfterAuthentication
    @Override
    public GroupEntity getById(Long id) throws Exception {
        Optional<GroupEntity> optional = groupDao.findById(id);
        if (optional.isEmpty()) {
            throw new IllegalAccessException("non-existent");
        }
        return optional.get();
    }

    /**
     * 获取真实的管理的组织ID
     *
     * @return
     * @throws IllegalAccessException
     */
    @Override
    public List<Long> getPrincipal(String account) throws IllegalAccessException {

        UserEntity entity = userDao.findByAccount(account);
        Long uid = entity.getId();
        Long gid = entity.getGid();
        Long pid = entity.getPid();

        if (UserEntity.Identity.SUPER.code.equals(entity.getIdentity())
                || UserEntity.Identity.ADMIN.code.equals(entity.getIdentity())) {
            List<GroupEntity> all = groupDao.findAll();
            return all.stream().map(GroupEntity::getId).collect(Collectors.toList());
        } else if (UserEntity.Identity.GROUP_ADMIN.code.equals(entity.getIdentity())) {
            uid = uid;
        } else if (UserEntity.Identity.GROUP.code.equals(entity.getIdentity())) {
            uid = pid;
        } else {
            return List.of(gid);
        }
        if (uid == 0) {
            throw new IllegalAccessException("用户权限检查失败");
        }
        Optional<UserEntity> optional = userDao.findById(uid);
        if (optional.isEmpty()) {
            throw new IllegalAccessException("用户不存在");
        }
        UserEntity userEntity = optional.get();
        String acc = userEntity.getAccount();
        if (!StringUtils.hasLength(acc)) {
            throw new IllegalAccessException("用户账号不存在");
        }
        List<GroupEntity> all = groupDao.findAllByPrincipal(acc);
        List<Long> ids = all.stream().map(GroupEntity::getId).collect(Collectors.toList());
        return ids;
    }

    /**
     *     更换代理人
     * @param groupId 变更的组织
     * @param principal 上任的用户
     */
    @Transactional
    @Override
    public void replacePrincipal(Long groupId,String principal) throws IllegalAccessException {
        Optional<GroupEntity> optional = groupDao.findById(groupId);
        if (optional.isEmpty()) {
            throw new IllegalAccessException("组织不存在");
        }
        UserEntity userEntity = userDao.findByAccount(principal);
        if (userEntity == null) {
            throw new IllegalAccessException("用户不存在");
        }
        JwtAuthenticationToken authentication = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        String role;
        try {
            role = authentication.getToken().getClaim("role");
        } catch (Exception e) {
            throw new IllegalAccessException("权限不存在");
        }
        if (!StringUtils.hasLength(role)) {
            throw new IllegalAccessException("权限不存在");
        }

        if (!UserEntity.Identity.SUPER.code.equals(role) && !UserEntity.Identity.ADMIN.code.equals(role)) {
            throw new IllegalAccessException("您没有超级管理权限");
        }

        this.changePrincipal(userEntity,optional.get());
    }

    @BeforeAuthentication
    @Transactional
    @Override
    public GroupEntity add(GroupEntity param) throws Exception {
        param.setId(null);
        UserEntity userEntity = userDao.findByAccount(param.getPrincipal());
        if (userEntity == null) {
            throw new IllegalAccessException("用户不存在");
        }
        if (!UserEntity.Identity.SIMPLE.code.equals(userEntity.getIdentity())
                && !UserEntity.Identity.GROUP.code.equals(userEntity.getIdentity())) {
            throw new IllegalAccessException("用户身份不是普通用户");
        }
        if (!userEntity.getStats()) {
            throw new IllegalAccessException("用户状态已停用");
        }
        param.setStatus(true);
        GroupEntity entity = groupDao.save(param);
        changePrincipal(userEntity, entity);
        return entity;
    }

    @Transactional
    @Override
    public GroupEntity set(GroupEntity param) throws Exception {
        GroupEntity entity = getById(param.getId());

        return null;
    }

    // 事务由 userService.setState 控制
    @Override
    public void setStatus(Long gid, int state) throws Exception {
        boolean b = state != 0;
        GroupEntity entity = getById(gid);
        if (entity.getStatus() == b) {
            return;
        }
        entity.setStatus(b);
        Boolean status = entity.getStatus();

        List<UserEntity> list = userDao.findAllByGidAndDelIsNull(entity.getId());
        for (UserEntity userEntity : list) {
            if (userEntity.getStats() != status) {
                userService.setState(userEntity.getId(),state);
            }
        }
        groupDao.save(entity);
    }


    /**
     *
     * @param user 上任的用户
     * @param group 变更的组织
     */
    private void changePrincipal(UserEntity user, GroupEntity group) {
        String principal = group.getPrincipal();
        long superUser  = 0;
        List<UserEntity> list = userDao.findAllByIdentity(UserEntity.Identity.SUPER.code);
        if (!list.isEmpty()) {
            superUser = list.get(0).getId();
        }
        if (StringUtils.hasLength(principal) && !group.getPrincipal().equals(user.getAccount())) {
            UserEntity oldUser = userDao.findByAccount(principal);
            List<GroupEntity> oldGroup = groupDao.findAllByPrincipal(oldUser.getAccount());
            if (oldGroup.size() < 2) { // 原有用户没有担任其它组织的当事人，改变上级
                oldUser.setPid(user.getId());
                oldUser.setGid(group.getId());
                oldUser.setIdentity(UserEntity.Identity.SIMPLE.code);
                userAuthorityDao.deleteByUserIdAndAuthorityCodeStartingWith(oldUser.getId(),"Group");
            } else { // 有其它组织，选其中一个
                Optional<GroupEntity> optional = oldGroup.stream().filter(it -> it.getId() != group.getId().longValue()).findFirst();
                if (optional.isPresent()) {
                    oldUser.setGid(optional.get().getId());
                }
            }

            // 更改下面的用户
            List<UserEntity> childAll = userDao.findAllByPid(oldUser.getId());
            for (UserEntity userEntity : childAll) {
                if (userEntity.getGid() == group.getId().longValue()) {
                    userEntity.setPid(user.getId());
                }
            }
            childAll.add(oldUser);
            userDao.saveAll(childAll);
        }
        // 检查上任的用户是否担任其它组织当事人
        List<GroupEntity> groupList = groupDao.findAllByPrincipal(user.getAccount());
        if (groupList.isEmpty()) { // 没有 更改组织ID
            user.setGid(group.getId());
        }
        user.setIdentity(UserEntity.Identity.GROUP_ADMIN.code);
        user.setPid(superUser);
        group.setPrincipal(user.getAccount());
        groupDao.save(group);
        userDao.save(user);
        // 设置权限
        List<AuthorityEntity> entityList = authorityDao.findAllByGidAndCodeStartingWith(0L, "Group");
        for (AuthorityEntity entity : entityList) {
            UserAuthorityEntity build = UserAuthorityEntity.builder().authorityCode(entity.getCode()).userId(user.getId()).account(user.getAccount()).codeGid(entity.getGid()).build();
            userAuthorityDao.save(build);
        }
    }

}
